/***********************************************************************
*  File - endian.h
*
*  Description -
*
*   Contains GENERIC macros to swap bytes words lwords bytes within buffer
*
*   This file is meant to address endian issues. In the case of NT and
*
*   and all other OSs running in little endian platforms, the macros are
*   NULL.
*
*   In the future we must replace SOLARIS_SPARC with BIG_ENDIAN or
*   something similar if other big endian processors are supported.
*
*
*   Copyright (c) 2004  NMS Communications Corp.  All rights reserved.
***********************************************************************/

#ifndef ENDIAN_DEF
#define ENDIAN_DEF

#if defined (LINUX)
#include "/usr/include/endian.h"
/*
 * HACK HACK HACK HACK HACK HACK HACK HACK HACK HACK HACK HACK
 *
 * NMS has a header file named "endian.h".
 * Linux has a header file named "endian.h".
 * If you #include <endian.h>, you're likely to get the NMS file
 * which will screw up all sorts of operations (like ctype).
 * So we directly include the Linux "endian.h" file here by
 * specifying its absolute path. So you get both.
 */
#endif

#define NMS_LOWORD(x) ((WORD) (x))
#define NMS_HIWORD(x) ((WORD) ((x) >> 16))
#define NMS_MAKEDWORD(h,l) ((DWORD) (((WORD) (l)) | ((DWORD) ((WORD) (h))) << 16))

#define NMS_ALIGN(v) ((v + sizeof(DWORD) - 1) & ~(sizeof(DWORD) - 1))

/* just a test */
#ifdef SOLARIS_SPARC
#define  BIG_ENDIAN_PROC
#endif


#ifdef  BIG_ENDIAN_PROC

#ifndef SWAPDWORD
#define SWAPDWORD(XDWORD)\
        (((XDWORD) << 24) | ((XDWORD) << 8 & 0x00ff0000) |\
     ((XDWORD) >> 24 & 0x000000ff) | ((XDWORD) >> 8 & 0x0000ff00))
#endif /* SWAPDWORD */

#define SWAPDW(x) (((x) << 16) | ((x) >> 16 & 0x0000ffff))

#define SWAPBYTES(x) ((((x) & 0x00ff ) << 8) | ((x) >> 8 & 0x00ff))
/*Get UnAligned Swapped  Word */
#define GetUASW(addr,val) { char *_a=(char*)(addr);\
                               union { struct {char c0;char c1;} _c; short _l;} _u;\
                               _u._c.c1=*_a++;_u._c.c0=*_a;(val)=_u._l;}
/*Get UnAligned Swapped Double Word */
#define GetUASDW(addr,val) { char *_a=(char*)(addr);\
                               union { struct {char c0;char c1;char c2;char c3;} _c; DWORD _l;} _u;\
                               _u._c.c3=*_a++;_u._c.c2=*_a++;_u._c.c1=*_a++;_u._c.c0=*_a;(val)=_u._l;}
/*Get UnAligned half Swapped Double Word */
#define GetUA_SDW(addr,val) { char *_a=(char*)(addr);\
                               union { struct {char c0;char c1;char c2;char c3;} _c; DWORD _l;} _u;\
                               _u._c.c2=*_a++;_u._c.c3=*_a++;_u._c.c0=*_a++;_u._c.c1=*_a;(val)=_u._l;}
/*Set UnAligned Swapped Double Word */
#define SetUASDW(addr,val) { char *_a=(char*)(addr);\
                               union { struct {char c0;char c1;char c2;char c3;} _c; DWORD _l;} _u;_u._l=(val);\
                               *_a++=_u._c.c3;*_a++=_u._c.c2;*_a++=_u._c.c1;*_a=_u._c.c0;}
/*Swap UnAligned Double Word */
#define SwapUADW(addr) { char *_a=(char*)(addr);\
                               union { struct {char c0;char c1;char c2;char c3;} _c; DWORD _l;} _u;\
                               _u._c.c3=*_a++;_u._c.c2=*_a++;_u._c.c1=*_a++;_u._c.c0=*_a;_a=(char*)(addr);\
                               *_a++=_u._c.c0;*_a++=_u._c.c1;*_a++=_u._c.c2;*_a=_u._c.c3;}

/* b - pointer to buffer or struct, t - type , size - size in bytes */
#define SWAPBUF( b, t ) \
       {\
          t * dptr = ( t * )b;\
          int j = sizeof(b) / sizeof(t);\
          while (j > 0)\
          {\
            if( sizeof(ushort) == sizeof (t) )\
                *dptr = SWAPBYTES( * dptr );\
            else \
                *dptr = SWAPDWORD( * dptr );\
            dptr++;\
            j --;\
          }\
       }


#define SWAPBUFSIZE(t, p, c) \
       {\
          t *ptr = (t *)(p);\
      int i;\
      for (i = (c); i > 0; i--, ptr++)\
      {\
        if (sizeof(ushort) == sizeof(t))\
        *ptr = SWAPBYTES(*ptr);\
        else \
        *ptr = SWAPDWORD(*ptr);\
      }\
       }

#define ADJUSTBUF(t, p, c) \
       {\
          t *ptr = (t *)(p);\
      int i;\
      for (i = (c); i > 0; i--, ptr++)\
      {\
        if (sizeof(ushort) == sizeof(t))\
        *ptr = SWAPBYTES(*ptr);\
        else \
        *ptr = SWAPDWORD(*ptr);\
      }\
       }

#define MAKEWORDBE(w) (w)
#define RESTOREWORDBE(w) (w)

#else   // Little Endian processors - Do nothing


#define SWAPDWORD(XDWORD) ((DWORD) (XDWORD))
#define SWAPDW(x) ((DWORD) (x))

#define SWAPBYTES(x) (x)

#define SWAPBUF(b, t)
#define ADJUSTBUF(t, p, c)

#define MAKEWORDBE(w) ((((w) & 0xff) << 8) | (((w) >> 8) & 0xff))
#define RESTOREWORDBE(w) ((((w) & 0xff) << 8) | (((w) >> 8) & 0xff))


#endif /* BIG_ENDIAN_PROC */

// Create more generic alias names for the above macros.  These names signify
// conversion of data from Host format (Big or Little Endian) to NMS board
// format (currently Little Endian)

#define H2NMS_DWORD(XDWORD)  SWAPDWORD ( (XDWORD) )
#define NMS2H_DWORD(XDWORD)  SWAPDWORD ( (XDWORD) )

#define H2NMS_SWAPDW(x)      SWAPDW ( (x) )
#define NMS2H_SWAPDW(x)      SWAPDW ( (x) )

#define H2NMS_WORD(x)       SWAPBYTES ( (x) )
#define NMS2H_WORD(x)       SWAPBYTES ( (x) )

#define H2NMS_BUF(b,t)         SWAPBUF ( (b), (t) )
#define NMS2H_BUF(b,t)         SWAPBUF ( (b), (t) )


#endif /* ENDIAN_DEF */

